package jfconfig;

/**
 * Created : Mar 16, 2012
 *
 * @author pquiring
 */

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

import javaforce.*;;

public class RoutingRouteDialog extends javax.swing.JDialog implements KeyListener {

  /**
   * Creates new form RoutingRouteDialog
   */
  public RoutingRouteDialog(java.awt.Frame parent, boolean modal, RoutingPanel.Route route) {
    super(parent, modal);
    initComponents();
    setPosition();
    listInterfaces();
    dest.addKeyListener(this);
    mask.addKeyListener(this);
    gw.addKeyListener(this);
    if (route == null) return;
    dest.setText(route.dest);
    mask.setText(route.mask);
    metric.setValue(route.metric);
    String via = route.via;
    if (via.startsWith("gw ")) {
      use_gw.setSelected(true);
      gw.setText(via.substring(3));
    }
    if (via.startsWith("dev ")) {
      use_dev.setSelected(true);
      String devName = via.substring(4);
      for(int a=0;a<ifNames.size();a++) {
        if (ifNames.get(a).equals(devName)) {
          dev.setSelectedIndex(a);
          break;
        }
      }
    }
  }

  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  @SuppressWarnings("unchecked")
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    buttonGroup1 = new javax.swing.ButtonGroup();
    jLabel1 = new javax.swing.JLabel();
    jLabel2 = new javax.swing.JLabel();
    dest = new javax.swing.JTextField();
    mask = new javax.swing.JTextField();
    use_dev = new javax.swing.JRadioButton();
    dev = new javax.swing.JComboBox();
    use_gw = new javax.swing.JRadioButton();
    gw = new javax.swing.JTextField();
    accept = new javax.swing.JButton();
    cancel = new javax.swing.JButton();
    jLabel3 = new javax.swing.JLabel();
    metric = new javax.swing.JSpinner();

    setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

    jLabel1.setText("Destination");

    jLabel2.setText("NetMask");

    buttonGroup1.add(use_dev);
    use_dev.setSelected(true);
    use_dev.setText("Interface");
    use_dev.addItemListener(new java.awt.event.ItemListener() {
      public void itemStateChanged(java.awt.event.ItemEvent evt) {
        use_devItemStateChanged(evt);
      }
    });

    buttonGroup1.add(use_gw);
    use_gw.setText("Gateway");
    use_gw.addItemListener(new java.awt.event.ItemListener() {
      public void itemStateChanged(java.awt.event.ItemEvent evt) {
        use_gwItemStateChanged(evt);
      }
    });

    gw.setEnabled(false);

    accept.setText("Accept");
    accept.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        acceptActionPerformed(evt);
      }
    });

    cancel.setText("Cancel");
    cancel.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        cancelActionPerformed(evt);
      }
    });

    jLabel3.setText("Metric");

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
              .addComponent(jLabel1)
              .addComponent(jLabel2))
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
              .addComponent(dest)
              .addComponent(mask)))
          .addGroup(layout.createSequentialGroup()
            .addComponent(use_gw)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(gw))
          .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
            .addGap(0, 0, Short.MAX_VALUE)
            .addComponent(cancel)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(accept))
          .addGroup(layout.createSequentialGroup()
            .addComponent(use_dev)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(dev, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addGap(0, 182, Short.MAX_VALUE))
          .addGroup(layout.createSequentialGroup()
            .addComponent(jLabel3)
            .addGap(48, 48, 48)
            .addComponent(metric)))
        .addContainerGap())
    );
    layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(jLabel1)
          .addComponent(dest, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(jLabel2)
          .addComponent(mask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(use_dev)
          .addComponent(dev, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(use_gw)
          .addComponent(gw, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(jLabel3)
          .addComponent(metric, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(accept)
          .addComponent(cancel))
        .addContainerGap())
    );

    pack();
  }// </editor-fold>//GEN-END:initComponents

  private void use_devItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_use_devItemStateChanged
    if (use_dev.isSelected()) {
      dev.setEnabled(true);
      gw.setEnabled(false);
    }
  }//GEN-LAST:event_use_devItemStateChanged

  private void cancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelActionPerformed
    dispose();
  }//GEN-LAST:event_cancelActionPerformed

  private void acceptActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_acceptActionPerformed
    if (!valid()) return;
    accepted = true;
    dispose();
  }//GEN-LAST:event_acceptActionPerformed

  private void use_gwItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_use_gwItemStateChanged
    if (use_gw.isSelected()) {
      dev.setEnabled(false);
      gw.setEnabled(true);
    }
  }//GEN-LAST:event_use_gwItemStateChanged

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JButton accept;
  private javax.swing.ButtonGroup buttonGroup1;
  private javax.swing.JButton cancel;
  private javax.swing.JTextField dest;
  private javax.swing.JComboBox dev;
  private javax.swing.JTextField gw;
  private javax.swing.JLabel jLabel1;
  private javax.swing.JLabel jLabel2;
  private javax.swing.JLabel jLabel3;
  private javax.swing.JTextField mask;
  private javax.swing.JSpinner metric;
  private javax.swing.JRadioButton use_dev;
  private javax.swing.JRadioButton use_gw;
  // End of variables declaration//GEN-END:variables

  public boolean accepted = false;
  private ArrayList<String> ifNames = new ArrayList<String>();

  public String getDest() { return dest.getText(); }
  public String getMask() { return mask.getText(); }
  public boolean getUseDev() { return use_dev.isSelected(); }
  public boolean getUseGw() { return use_gw.isSelected(); }
  public String getDev() { return (String)dev.getSelectedItem(); }
  public String getGw() { return gw.getText(); }
  public int getMetric() { return (Integer)metric.getValue(); }

  private void listInterfaces() {
    //exec "ifconfig"
    ShellProcess sp = new ShellProcess();
    ArrayList<String> cmd = new ArrayList<String>();
    cmd.add("ifconfig");
    String output = sp.run(cmd, false);
    if (output == null) {
      JFAWT.showError("Error", "Failed to exec ifconfig.");
      return;
    }
    String lns[] = output.split("\n");
    for(int a=0;a<lns.length;a++) {
      if (lns[a].length() == 0) continue;
      if (lns[a].charAt(0) == ' ') continue;
      int idx = lns[a].indexOf(' ');
      String intface = lns[a].substring(0, idx);
//      if (intface.equals("lo")) continue;  //useful?
      ifNames.add(intface);
      dev.addItem(intface);
    }
  }

  private boolean isIP4Valid(JTextField tf, boolean nullAllowed) {
    String str = tf.getText();
    tf.setBackground(new Color(0xff0000));
    if (str.length() == 0) return nullAllowed;
    String octs[] = str.split("[.]", -1);
    if (octs.length != 4) {JFLog.log("octs.length=" + octs.length); return false;}
    try {
      for(int a=0;a<4;a++) {
        int test = Integer.valueOf(octs[a]);
        if ((test < 0) || (test > 255)) return false;
      }
    } catch (Exception e) {
      JFLog.log(e);
      return false;
    }
    tf.setBackground(new Color(0xffffff));
    return true;
  }

  private boolean isNumberValid(JSpinner sp) {
    sp.setBackground(new Color(0xff0000));
    int v = (Integer)sp.getValue();
    if ((v<0) || (v>65535)) return false;
    sp.setBackground(new Color(0xffffff));
    return true;
  }

  private boolean valid() {
    if (!isIP4Valid(dest, false)) return false;
    if (!isIP4Valid(mask, false)) return false;
    if (use_gw.isSelected()) {
      if (!isIP4Valid(gw, false)) return false;
    }
    if (!isNumberValid(metric)) return false;
    return true;
  }

  public void keyPressed(KeyEvent e) {}
  public void keyReleased(KeyEvent e) {valid();}
  public void keyTyped(KeyEvent e) {}

  private void setPosition() {
    Rectangle s = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
    Dimension d = getSize();
    setLocation(s.width/2 - d.width/2, s.height/2 - (d.height/2));
  }

}
